<?php
/**
 * FastApp.
 * 8/12/24
 * @Author 深色的海 (wx:deepsea_0024)
 * @Contact telegram:deepsea159
 */

namespace App\Game\Api\Service\Platform;

use App\Fastapp\Api\Service\Account\WalletService;
use App\Fastapp\Exception\TipException;
use App\Fastapp\Model\AccountInfo;
use App\Fastapp\Model\AccountWallet;
use App\Fastapp\Model\AccountWalletLog;
use App\Game\Listener\Event\BetEvent;
use App\Game\Model\Game;
use App\Game\Model\GameAccountRtp;
use App\Game\Model\GameBet;
use App\Game\Model\GamePlatform;
use GuzzleHttp\Client;

class GamepgService implements GameInterface
{
    public static array $config = [];
    const CODE = 'gamepg';
    const CURRENCY = [
        'BRL',/* 'EUR', 'GBP', 'IDR', 'INR', 'JPY',
        'KRW', 'MMK', 'MXN', 'NGN', 'PHP', 'PKR',
        'RUB', 'SAR', 'THB', 'TRY', 'VND', 'ZAR',
        'USD', 'USDT'*/
    ];

    public static function syncGameList(): bool
    {
        list($res, $config) = self::post('/gi/v1/egame/get-list');
        $in = [];
        $exit = Game::query()->where(['platform' => self::CODE])->pluck('code')->toArray();
        $t = date('Y-m-d H:i:s');
        foreach ($res['data']['games'] as $item) {
            if ($item['status'] != 1) continue;
            if (in_array($item['gameId'], $exit)) continue;
            $in[] = [
                'name' => json_encode([
                    [
                        'lang' => 'all',
                        'text' => $item['gameName']
                    ],
                    [
                        'lang' => 'zh_Hans',
                        'text' => $item['gameNameZh']
                    ],
                ], JSON_UNESCAPED_UNICODE),
                'code' => $item['gameId'],
                'platform' => self::CODE,
                'provider' => self::CODE,
                'rtp' => $config['rtp'],
                'type' => $item['gameType'],
                'cover' => '/images/game/gamepg/' . $item['gameName'] . '.png',
                'status' => 1,
                'created_at' => $t,
                'updated_at' => $t,
            ];
        }
        if ($in) Game::query()->insert($in);
        return true;
    }

    public static function gamePlayUrl(array $data): string
    {
        list($res) = self::post('/gi/v1/egame/get-game-addr', [
            'gameId' => (int)$data['code'],
            'userId' => '' . $data['gac_id'],
            'language' => $data['lang'],
        ]);
        if ($res['code'] != 1) throw new TipException(fastapp_t('game.game_not_find'));
        return $res['data']['addr'];
    }

    public static function createUser(int|string $uid, string $symbol, string $provider = ''): void
    {
        $rtp = GamePlatform::query()->where(['code' => self::CODE])->value('rtp');
        $md = GameAccountRtp::query()->create([
            'code' => self::CODE,
            'user_id' => $uid,
            'rtp' => $rtp,
            'symbol' => $symbol,
            'provider' => $provider,
        ]);
        try {
            list($res) = self::post('/gi/v1/merchant/create-user', [
                'currency' => $symbol,
                'userId' => '' . $md->id,
                'nickname' => AccountInfo::query()->where(['user_id' => $uid])->value('nickname'),
            ]);
            if ($res['code'] == 1) {
                self::setUserRtp([['userId' => '' . $md->id, 'rtp' => $rtp]]);
                return;
            }
        } catch (\Throwable) {
        }
        $md->delete();
        sys_notify(fastapp_t('game.game_account_fail'));
    }

    public static function killUser(int|string $user_id): bool
    {
        $game_user_id = GameAccountRtp::query()->where(['user_id' => $user_id, 'code' => self::CODE])->value('id');
        list($res) = self::post('/gi/v1/merchant/kill-user', ['userId' => '' . $game_user_id]);
        if ($res['code'] == 1) return true;
        throw new TipException(fastapp_t('game.game_ac_not_sync'));
    }

    public static function setUserRtp(array $list): bool
    {
        list($res) = self::post('/gi/v1/rtp/updates', [
            'list' => $list
        ]);
        if ($res['code'] == 1) return true;
        return false;
    }

    public static function getUserRtp(array $list): bool
    {
        list($res) = self::post('/gi/v1/rtp/check', [
            'userIds' => $list
        ]);
        if ($res['code'] == 1) return true;
        return false;
    }

    public static function getBalance(array $data): array
    {
        list(, $sign) = GamepgService::getSign($data['tax']);
        if ($data['sign'] == $sign) {
            $game_user_id = $data['userId'];
            $user_id = GameAccountRtp::query()->where(['id' => $game_user_id])->value('user_id');
            $res = get_user_cache(['symbol', 'gameid'], $user_id);
            $is_demo = Game::query()->where(['id' => $res['gameid']])->value('demo');
            $wallet = AccountWallet::query()->where(['user_id' => $user_id, 'symbol' => $res['symbol']])->first(['balance', 'balance_demo']);
            return [
                'code' => 1,
                'tax' => $data['tax'],
                'balance' => intval($is_demo ? $wallet->balance_demo : $wallet->balance * 100)
            ];
        }
        return ['code' => 0];
    }

    public static function transaction(array $data): array
    {
        list(, $sign) = GamepgService::getSign($data['tax']);
        if ($data['sign'] == $sign) {
            $game_user_id = $data['userId'];
            $user_id = GameAccountRtp::query()->where(['id' => $game_user_id])->value('user_id');
            $res = get_user_cache(['symbol', 'gameid', 'type'], $user_id);
            $is_demo = Game::query()->where(['id' => $res['gameid']])->value('demo');
            $bet = $data['bet'] / 100;
            $payout = $data['payout'] / 100;
            $result = 1;
            $amount = $bet - $payout;
            if ($amount > 0) $result = 3; elseif ($amount < 0) $result = 2;
            $md = GameBet::query()->create([
                'user_id' => $user_id,
                'game_id' => $res['gameid'],
                'bet_id' => $data['normalRecordId'],
                'transaction_id' => $data['tradeId'],
                'platform' => self::CODE,
                'amount' => $bet,
                'payout' => $payout,
                'result_amount' => abs($amount),
                'rtp' => $data['rtp'],
                'symbol' => $res['symbol'],
                'result' => $result,
            ]);
            if (!$md->wasRecentlyCreated) return ['code' => 4];
            $ord = [
                'user_id' => $user_id,
                'symbol' => $res['symbol'],
                'amount' => $bet,
                'type' => AccountWalletLog::USE_BALANCE,
                'object_type' => AccountWalletLog::OBJ_TYPE_GAME_BAT,
                'object_id' => $md->id,
            ];
            WalletService::dec($ord, null, $is_demo ? 'balance_demo' : 'balance');
            if ($bet) {
                $ord['amount'] = $bet;
                $ord['type'] = AccountWalletLog::RECHARGE;
                $wallet = WalletService::inc($ord, null, $is_demo ? 'balance_demo' : 'balance');
            } else {
                $wallet = AccountWallet::query()->select(['balance', 'balance_demo'])->where(['user_id' => $user_id, 'symbol' => $res['symbol']])->first();
            }
            api_dispatch(new BetEvent($user_id, $md->id, $res['type']));
            return [
                'code' => 1,
                'tradeId' => $data['tradeId'],
                'tax' => $data['tax'],
                'balance' => intval($is_demo ? $wallet->balance_demo : $wallet->balance * 100)
            ];
        }
        return ['code' => 2];

    }

    public static function getSign(int $tax = 0): array
    {
        $config = self::getConfig();
        $tax = $tax ?: random_int(1000, 9999);
        return [$tax, md5(implode('|', [$config['merchant_id'], $tax, $config['secret_key']])), $config];
    }

    public static function post(string $uri, array $data = []): array
    {
        list($tax, $sign, $config) = self::getSign();
        $data['merAccount'] = $config['merchant_id'];
        $data['sign'] = $sign;
        $data['tax'] = $tax;
        $client = new Client(['base_uri' => $config['url']]);
        $response = $client->post($uri, [
            'json' => $data
        ]);
        return [json_decode($response->getBody()->getContents(), true), $config];
    }

    public static function getConfig(bool $refresh = false): array
    {
        if (!self::$config || $refresh) {
            $md = GamePlatform::query()->where(['code' => self::CODE])->first(['config', 'rtp']);
            self::$config = array_column($md->config, 'text', 'field');
            self::$config['rtp'] = $md->rtp;
        }
        return self::$config;
    }

    public static function getQuota(string $symbol): array
    {
        // TODO: Implement getQuota() method.
    }
}